#include <iostream>
#include <memory>

// 1.简单工厂模式
//  优点：简单粗暴，直观易懂。使⽤⼀个⼯⼚⽣产同⼀等级结构下的任意产品
//  缺点：
//  1. 所有东西⽣产在⼀起，产品太多会导致代码量庞⼤
//  2. 开闭原则遵循(开放拓展，关闭修改)的不是太好，要新增产品就必须修改⼯⼚⽅法。
class Fruit
{
public:
    virtual void name() = 0; // 纯虚函数
    // 包含纯虚函数的类被称为抽象类，抽象类不能被实例化,只能被用作基类来派生其他类
    // 派生类必须重写纯虚函数，除非派生类本身也是抽象类
};

class Apple : public Fruit
{
public:
    void name() override
    {
        std::cout << "苹果" << std::endl;
    }
};

class Banana : public Fruit
{
public:
    void name() override
    {
        std::cout << "香蕉" << std::endl;
    }
};

//产品2：动物
class Animal
{
public:
    virtual void name() = 0;
};

class Dog : public Animal
{
public:
    void name() override {
        std::cout << "土狗" <<std::endl;
    }
};

class Lamp : public Animal
{
public:
    void name() override {
        std::cout << "山羊" <<std::endl;
    }
};


// class FruitFactory
// {
// public:
//     static std::shared_ptr<Fruit> getFruit(const std::string name)
//     {
//         if (name == "苹果")
//         {
//             return std::make_shared<Apple>();
//         }
//         else
//         {
//             return std::make_shared<Banana>();
//         }
//     }
// };

//2.工厂方法模式 ；一个产品对应一个生产工厂
//缺点：可能会造成类太多，代繁琐
//优点：遵循开闭原则
// class FruitFactory
// {
// public:
//     virtual std::shared_ptr<Fruit> getFruit() = 0;
// };

// class AppleFactory : public FruitFactory
// {
// public:
//     std::shared_ptr<Fruit> getFruit() override {
//         return std::make_shared<Apple>();
//     }
// };
// class BananaFactory : public FruitFactory
// {
// public:
//     std::shared_ptr<Fruit> getFruit() override {
//         return std::make_shared<Banana>();
//     }
// };

// 3.抽象⼯⼚：围绕⼀个超级⼯⼚创建其他⼯⼚。每个⽣成的⼯⼚按照⼯⼚模式提供对象。
// 思想：将⼯⼚抽象成两层，抽象⼯⼚ & 具体⼯⼚⼦类， 在⼯⼚⼦类种⽣产不同类型的⼦产品
class Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string name) = 0;
    virtual std::shared_ptr<Animal> getAnimal(const std::string name) = 0;
};

class FruitFactory : public Factory
{
public:
    std::shared_ptr<Animal> getAnimal(const std::string name) override
    {
        return nullptr;
    }
    
    std::shared_ptr<Fruit> getFruit(const std::string name) override
    {
        if(name == "苹果")
        {
            return std::make_shared<Apple>();
        }
        else
        {
            return std::make_shared<Banana>();
        }
    }
};

class AnimalFactory : public Factory
{
public:
    virtual std::shared_ptr<Fruit> getFruit(const std::string name)
    {
        return nullptr;
    }
    virtual std::shared_ptr<Animal> getAnimal(const std::string name)
    {
        if(name == "土狗")
        {
            return std::make_shared<Dog>();
        }
        else
        {
            return std::make_shared<Lamp>();
        }
    }
};

class FactoryProducer
{
public:
    static std::shared_ptr<Factory> create(const std::string name)
    {
        if(name == "水果")
        {
            return std::make_shared<FruitFactory>();
        }
        else
        {
            return std::make_shared<AnimalFactory>();
        }
    }
};


int main()
{
    // std::shared_ptr<Fruit> p = FruitFactory::getFruit("苹果");
    // p->name();
    // p = FruitFactory::getFruit("香蕉");
    // p->name();

    // std::shared_ptr<FruitFactory> f(new AppleFactory());
    // std::shared_ptr<Fruit> a = f->getFruit();//f->getFruit()构成工厂多态
    // a->name();//构成水果多态
    // f.reset(new BananaFactory());
    // std::shared_ptr<Fruit> b = f->getFruit();
    // b->name();

    std::shared_ptr<Factory> ff = FactoryProducer::create("水果");
    std::shared_ptr<Fruit> a = ff->getFruit("苹果");
    a->name();

    std::shared_ptr<Factory> af = FactoryProducer::create("动物");
    std::shared_ptr<Animal> an = af->getAnimal("土狗");
    an->name();
    
    return 0;
}
